<?php
require_once 'helper.php';

class Model {

    protected $_data = array();
    protected $_isDeleted = false;
    protected $_changedFields = array();
	
    // descendant class init this value
    protected $_idFieldName = null;
    protected $_entityName = null;
    protected $_db = null;
    
	public function __construct() {
	}
	
    public function getData($key=null) {
		if (!$key) 
			return $this->_data;
		else
			return isset($this->_data[$key]) ? $this->_data[$key] : null;
    }
	
    public function setData($key, $value=null) {
		$this->_data[$key] = $value;
		if (!in_array($key, $this->_changedFields)) array_push($this->_changedFields, $key);
        return $this;
    }

    public function addData($data) {
    	$this->_data = array_merge($this->_data, $data);
    	return $this;
    }
    
    public function __call($method, $args) {
        $key = underscore(substr($method,3));
    	
        switch (substr($method, 0, 3)) {
            case 'get' :
                $data = $this->getData($key, isset($args[0]) ? $args[0] : null);
                return $data;

            case 'set' :
                $result = $this->setData($key, isset($args[0]) ? $args[0] : null);
                return $result;

            case 'has' :
                return isset($this->_data[$key]);
        }
        throw new Exception("Invalid method ".get_class($this)."::".$method."(".print_r($args,1).")");
    }

    public function load($id) {
    	if (!$this->_db) return $this;
		$query = "SELECT * FROM ".$this->getEntityName()." WHERE ".$this->getIdFieldName()." = ".$id;
		$data = $this->_db->executeScalar($query);
    	if (!$data) return false;

		$this->addData($data);
    	return true;
    }
    
    public function save() {
    	if (!$this->_db) return $this;
    	if ($this->_isDeleted || empty($this->_changedFields)) return $this;

    	$result = false;
		if ($this->getId()) {	// perform update
			// get update string
			$upd = "";
			foreach($this->getData() as $key => $val) {
				if ($key != $this->getIdFieldName() && in_array($key, $this->_changedFields)) {
					$val = is_string($val)? "'$val', ": "$val, ";
					$upd .= "$key = $val, ";
				}
			}
			$upd = rtrim($upd, ", ");
			
			$query = "UPDATE ".$this->getEntityName()." SET ".$upd." WHERE ".$this->getIdFieldName()."=".$this->getId();
		} else { // insert
			// get insert keys\vals
			$keys = "";
			$vals = "";
			foreach($this->getData() as $key => $val) {
				if ($key != $this->getIdFieldName()) {
					$keys .= "$key, ";
					$vals .= is_string($val)? "'$val', ": "$val, ";
				}
			}
			$keys = rtrim($keys, ", ");
			$vals = rtrim($vals, ", ");
			
			$query = "INSERT INTO ".$this->getEntityName()."(".$keys.") VALUES(".$vals.")";
		}
		echo $query; die();
		$result = $this->_db->executeNonQuery($query);
		if ($result) $this->setData($this->getIdFieldName(), $this->_db->getInsertID());
		return $result;
    }
    
    public function delete() {
    	if (!$this->_db || !$this->getId()) return false;
		$query = "DELETE FROM ".$this->getEntityName()." WHERE ".$this->getIdFieldName()."=".$this->getId();
		$result= $this->_db->executeNonQuery($query);
		if ($result) $this->_isDeleted = true;
		return $result;
    }
    
    public function getIdFieldName() {
        return $this->_idFieldName;
    }

    public function getEntityName() {
        return $this->_entityName;
    }

    public function getId() {
        if ($this->getIdFieldName()) {
            return $this->getData($this->getIdFieldName());
        }
        return $this->getData('id');
    }
	
    public function getResource() {
    	return $this->_db;
    }

	public function createEntity($data) {
		$class = get_class($this);
		$result = new $class();
		$result->_db = $this->_db;
		return $result->addData($data);
	}
}

